<?php
/** Chứa các hàm toàn cục */
class App
{
    static $_configs = FALSE;
    static $_controllers = array();
    static $_controllers_loaded = false;

    public static function isAjaxRequest()
    {
        return isset($_SERVER['HTTP_X_REQUESTED_WITH'])
            && strcasecmp($_SERVER['HTTP_X_REQUESTED_WITH'], 'XMLHttpRequest') == 0;
    }

    public static function getConfig($group, $item = FALSE)
    {
        return Loader::getConfig($group, $item);
    }


    public static function password($pass)
    {
        $pass = App::getConfig('app', 'salt') . $pass;
        return hash('sha256', md5($pass));
    }

    public static function log($content)
    {
        $str = "[" . date('d/m/Y h:m') . "] " . print_r($content, true) . "\n";
        file_put_contents(Loader::getLogFile('debug'), $str, FILE_APPEND);
    }

    public static function debugLog($content)
    {
        $str = "[" . date('d/m/Y h:m') . "] " . print_r($content, true) . "\n";
        file_put_contents(Loader::getLogFile('debug'), $str);
    }

    public static function redirect($url)
    {
        header('location: ' . ROOT_URL . $url);
        exit();
    }

    public static function clearCookie()
    {
        foreach ($_COOKIE as $key => $value) {
            setcookie($key, '', time() - 1);
        }
    }

    # Lưu trữ URL trang trước để quay lại lúc cần
    public static function storeRefer($refer = null)
    {
        $_SESSION['refer'] = $refer == null ? $_SERVER['REQUEST_URI'] : $refer;
    }

    # Đặt exception vào SESSION để hiển thị lỗi
    public static function setException($ex, $refer = null, $exCode = 0)
    {
        if (is_string($ex)) {
            $ex = new Exception($ex, $exCode);
        }
        $_SESSION['exception'] = $ex;
        App::debugLog($ex);
        self::storeRefer($refer);
        self::redirect('error');
    }

    # Lấy ra exception
    public static function getException()
    {
        return isset($_SESSION['exception']) ? $_SESSION['exception'] : false;
    }

    # Lấy địa chỉ đã lưu trữ
    public static function getRefer()
    {
        return isset($_SESSION['refer']) ?
            preg_replace('#^' . ROOT_URL . '#', null, $_SESSION['refer']) :
            false;
    }

    # Lọc mảng, trả về một số phần tử
    public static function filterArray($array, $keys)
    {
        $result = array();
        foreach ($array as $key => $value) {
            in_array($key, $keys) && $result[$key] = $value;
        }

        return $result;
    }

    public static function formatVnd($num)
    {
        return number_format((float)$num * 1000, 0, '.', ',') . ' VND';
    }

    public static function formatVndShort($num)
    {
        $num = number_format($num, 0, '.', ',');
        return substr($num, 0, strlen($num) - 2) . ' triệu';
    }

    /** Thiết lập chế độ báo lỗi */
    public static function setReporting()
    {
        error_reporting(E_ALL);

        ini_set('log_errors', 'on');
        ini_set('error_log', Loader::getLogFile());
        ini_set('display_errors', Loader::getConfig('app', 'debug'));
    }

    /** Kiểm tra Magic Quotes và gỡ bỏ */

    public static function stripSlashesDeep($value)
    {
        $value = is_array($value) ? array_map(array(__CLASS__, 'stripSlashesDeep'), $value)
            : stripslashes($value);
        return $value;
    }

    public static function removeMagicQuotes()
    {
        if (get_magic_quotes_gpc()) {
            $_GET = self::stripSlashesDeep($_GET);
            $_POST = self::stripSlashesDeep($_POST);
            $_COOKIE = self::stripSlashesDeep($_COOKIE);
        }
    }

    /** Kiểm tra register global và gỡ bỏ */
    public static function unregisteredGlobals()
    {
        if (ini_get('register_globals')) {
            $array = array('_SESSION', '_POST', '_GET', '_COOKIE',
                '_REQUEST', '_SERVER', '_ENV', '_FILE');
            foreach ($array as $value) {
                foreach ($GLOBALS[$value] as $key => $var) {
                    if ($var == $GLOBALS[$key]) {
                        unset($GLOBALS[$key]);
                    }
                }
            }
        }
    }

    public static function getCaptchaCode()
    {
        if (isset($_SESSION[Loader::getConfig('captcha', 'session')])) {
            return $_SESSION[Loader::getConfig('captcha', 'session')];
        } else {
            return false;
        }
    }

    public static function captcha($userConfigs = null)
    {
        $configs = Loader::getConfig('captcha');
        if (is_array($userConfigs)) {
            $configs = array_merge($configs, $userConfigs);
        }

        $str = "";
        for ($i = 0; $i < $configs['length']; $i++) {
            // these numbers represent ASCII table (small letters)
            $str .= chr(rand(97, 122));
        }

        //md5 letters and saving them to session
        $letters = md5($str);
        $_SESSION[Loader::getConfig('captcha', 'session')] = $letters;

        //determine width and height for our image and create it
        $imgW = $configs['width'];
        $imgH = $configs['height'];
        $image = imagecreatetruecolor($imgW, $imgH);

        //setup background color and border color
        $bg_col = imagecolorallocate($image,
            $configs['bg_color'][0],$configs['bg_color'][1],$configs['bg_color'][2]);
        $br_col = imagecolorallocate($image,
            $configs['br_color'][0],$configs['br_color'][1],$configs['br_color'][2]);

//let's choose color in range of purple color
        $text_col = imagecolorallocate($image, rand(70,190),rand(10,170),rand(20,240));

//now fill rectangle and draw border
        imagefilledrectangle($image, 0, 0, $imgW, $imgH, $bg_col);
        imagerectangle($image, 0, 0, $imgW-1, $imgH-1, $br_col);

        $font = ROOT . 'resources/font-1.ttf';

//setup captcha letter size and angle of captcha letters
        $font_size = $imgH / 1.6;
        $angle = rand(-15,15);
        $box = imagettfbbox($font_size, $angle, $font, $str);
        $x = (int)($imgW - $box[4]) / 2;
        $y = (int)($imgH - $box[5]) / 2;
        imagettftext($image, $font_size, $angle, $x, $y, $text_col, $font, $str);

        header("Content-type: image/png");
        imagepng($image);
        imagedestroy ($image);
    }

    public static function genPassword()
    {
        $length = 8;
        $possible = '012346789bcdfghjkmnpqrtvwxyzBCDFGHJKLMNPQRTVWXYZ@#$%*!';
        $result = '';
        $len_possible = strlen($possible);
        for ($i = 0; $i < $length; $i++) {
            $rand = mt_rand(0, $len_possible - 1);
            $result .= $possible[$rand];
        }
        return $result;
    }

    public static function sendContentTypeHeader($type = 'text/plain')
    {
        header('Content-Type: ' . $type . '; charset=UTF-8');
    }

    public static function autoLoader($class)
    {
        if (Loader::loadClass($class) !== true) {
            throw new ErrorException("Không thể load class [$class]");
        }
    }

    public static function getPageNumber($str)
    {
        if (preg_match('#(?:trang-)?(\d+)#', $str, $match)) {
            return $match[1];
        } else {
            return 1;
        }
    }
    public static function initialApp()
    {
        self::setReporting();
        self::removeMagicQuotes();
        self::unregisteredGlobals();

        date_default_timezone_set(Loader::getConfig('app', 'timezone'));

        spl_autoload_register(array(__CLASS__, 'autoLoader'));

        set_exception_handler(array(__CLASS__, 'setException'));

        is_writable(ROOT . Loader::getConfig('app', 'cache_dir')) ||
            die('Không thể ghi dữ liệu vào thư mục cache [' . ROOT . Loader::getConfig('app', 'cache_dir') . ']');

        is_writable(ROOT . Loader::getConfig('app', 'log_dir')) ||
            die('Không thể ghi dữ liệu vào thư mục cache [' . ROOT . Loader::getConfig('app', 'log_dir') . ']');

        $databaseConfigs = Loader::getConfig('database');
        if ($databaseConfigs !== FALSE || Loader::getConfig('database', 'current') === FALSE) {
            $checkDbSuccess = false;
            foreach ($databaseConfigs as $config) {
                if (Database::check($config) === true) {
                    $checkDbSuccess = true;
                    Loader::setConfig('database', 'current', $config);
                    break;
                }
            }

            $checkDbSuccess || die('Kết nối đến cơ sở dữ liệu thất bại!');
        }

        # Config template
        SmTemplate::config(array(
            'cache_dir' => ROOT . Loader::getConfig('app', 'cache_dir'),
            'log' => ROOT . Loader::getConfig('app', 'log_dir') . 'template_log.text',
            'cache' => Loader::getConfig('app', 'template_cache')
        ));

        # Check cookie
        $uid_cookie_name = Loader::getConfig('cookie', 'username');
        $pwd_cookie_name = Loader::getConfig('cookie', 'password');
        if (isset($_COOKIE[$uid_cookie_name]) && isset($_COOKIE[$pwd_cookie_name])) {
            App::debugLog($_COOKIE);
            if (User::checkLogin(array(
                'encrypted' => true,
                'user' => $_COOKIE[$uid_cookie_name],
                'pass' => $_COOKIE[$pwd_cookie_name]
            ))) {
                UserController::setLogged($_COOKIE[$uid_cookie_name]);
            }
        }
    }
}